package org.bmind.datasword.utils.setup;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.bmind.datasword.config.dto.DConfig;
import org.bmind.datasword.config.dto.DData;
import org.bmind.datasword.config.dto.DDataset;
import org.bmind.datasword.config.dto.DChildDatasetContainer;
import org.bmind.datasword.config.dto.DMultiAnalisysContainer;
import org.bmind.datasword.config.dto.DParentDatasetContainer;
import org.bmind.datasword.config.dto.DMonoAnalisys;
import org.bmind.datasword.config.dto.DMultiAnalisys;
import org.bmind.datasword.config.dto.DPlot;
import org.bmind.datasword.config.dto.DPreProcFunction;
import org.bmind.datasword.config.dto.DPreProcess;
import org.bmind.datasword.config.impl.orient.OrientDConfig;
import org.bmind.datasword.config.impl.orient.OrientDataset;
import org.bmind.datasword.config.impl.orient.OrientMonoAnalisys;
import org.bmind.datasword.config.impl.orient.OrientMultiAnalisysContainer;
import org.bmind.datasword.config.impl.orient.OrientPreProcess;
import org.bmind.datasword.config.impl.orient.OrientUtilities;



import com.orientechnologies.orient.core.db.object.ODatabaseObject;
import com.orientechnologies.orient.core.db.object.ODatabaseObjectTx;
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;

public class Ordb2Pojo {
	private static ODatabaseObject	orDb;

	public Ordb2Pojo() {
		super();
	}

	/**
	 * 
	 * @param parameters
	 * @throws Exception
	 */
	public static void init(Map<String, Object> parameters) throws Exception {

		if (parameters.containsKey("url")) {
			orDb = new ODatabaseObjectTx((String) parameters.get("url"));
			if (parameters.containsKey("user")) {
				if (parameters.containsKey("password")) {
					orDb.open((String) parameters.get("user"), (String) parameters.get("password"));
				}
			}
		}
	}

	/**
	 * 
	 * @param orDB
	 */
	public static void init(ODatabaseObject orDB) {
		orDb = orDB;
	}

	/**
	 * Read object from OrientDb
	 * 
	 * @return DMonoAnalisys
	 */
	public static DMonoAnalisys dmono2pojo() {
		OrientMonoAnalisys oma = new OrientMonoAnalisys(orDb);
		List<DMonoAnalisys> localList = orDb.query(new OSQLSynchQuery<DMonoAnalisys>("select * from " + "DMonoAnalisys"));
		try {
			OrientUtilities.oLazyToEager(localList.get(0));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);
	}

	/**
	 * @author valerio
	 * Return a DMonoAnalisys object with the data filtered according to the roles and areas included.
	 * If no data is found return a null DMultiAnalisys.
	 * DData and DPlot check only roles
	 * DMonoAnalisys
	 * ...DData
	 *    DData
	 *    ...
	 * ...DPlot
	 *    DPlot
	 *    ...
	
	 * @param areas
	 * @param roles
	 * @return DMultiAnalisys
	 */
	public static DMonoAnalisys dmono2pojo( Collection<String> areas,Collection<String> roles) {
		OrientMonoAnalisys oma = new OrientMonoAnalisys(orDb);
		Collection<DData> locDData = new ArrayList<DData>();
		Collection<DPlot> locDPlot = new ArrayList<DPlot>();

		List<DMonoAnalisys> localList = orDb.query(new OSQLSynchQuery<DMonoAnalisys>("select * from DMonoAnalisys"));
		try {
			OrientUtilities.oLazyToEager(localList.get(0));
			// MonoAnalisys check areas & roles
			//System.out.println(localList.get(0).getRoles()+" "+ roles);
			
			if (CollectionUtils.containsAny(localList.get(0).getRoles(), roles) && CollectionUtils.containsAny(localList.get(0).getAreas(), areas)) {
				// DData  check areas & roles
				for (DData dd : localList.get(0).getListDData()) {
					//System.out.println(dd.getRoles().toString() + "  " + roles.toString());
					if (CollectionUtils.containsAny(dd.getRoles(), roles))
						locDData.add(dd);
				}
				localList.get(0).setListDData(locDData);
				// DPlot  check areas & roles
				for (DPlot dd : localList.get(0).getListDPlot()) {
					//System.out.println(dd.getRoles().toString() + "  " + roles.toString());
					if (CollectionUtils.containsAny(dd.getRoles(), roles))
						locDPlot.add(dd);
				}
				localList.get(0).setListDPlot(locDPlot);
			} else {
				localList.get(0).setListDPlot(locDPlot);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);
	}

	/**
	 * @deprecated
	 * @author valerio
	 * Return a DMultiAnalisys object not filtered.
	 * If no data is found return a null DMultiAnalisys.
	 * DMultiAnalisys
	 * ...DPlot
	 *    DPlot
	 *    ...
	 * ...DData
	 *    DData
	 *    ...
	 * @param areas
	 * @param roles
	 * @return DMultiAnalisysContainer
	 */
	public static DMultiAnalisys dmulti2pojo() {
		OrientMultiAnalisysContainer omu = new OrientMultiAnalisysContainer(orDb);
		List<DMultiAnalisys> localList = orDb.query(new OSQLSynchQuery<DMultiAnalisys>("select * from DMultiAnalisys"));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);

	}

	/**
	 * @author valerio
	 * Return a DMultiAnalisysContainer object with the data filtered according to the roles and areas included.
	 * If no data is found return a void DMultiAnalisysContainer.
	 * DData and DPlot check only roles
	 * DMultiAnalisysContainer
	 * 		DMultiAnalisys
	 * 		...DPlot
	 *    	   DPlot
	 *    	...
	 * 		...DData
	 *    	   DData
	 *    	...
	 *      DMultiAnalisys
	 * @param areas
	 * @param roles
	 * @return DMultiAnalisys
	 */
	public static DMultiAnalisysContainer dmulti2pojo(Collection<String> areas, Collection<String> roles) {
		Collection<DData> locDData = null;
		Collection<DPlot> locDPlot = null;
		Collection<DMultiAnalisys> locDMulti = null;
		OrientMultiAnalisysContainer omu = new OrientMultiAnalisysContainer(orDb);

		List<DMultiAnalisysContainer> localList = orDb.query(new OSQLSynchQuery<DMultiAnalisys>("select * from DMultiAnalisysContainer"));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
			// MultiAnalisysContainer check areas & roles
			if (CollectionUtils.containsAny(localList.get(0).getRoles(), roles) && (CollectionUtils.containsAny(localList.get(0).getAreas(), areas))) {
				// MultiAnalisys check areas & roles
				locDMulti = new ArrayList<DMultiAnalisys>();
				for (DMultiAnalisys ma : localList.get(0).getdMultiAnalisys()) {
					if (CollectionUtils.containsAny(ma.getRoles(), roles) && (CollectionUtils.containsAny(ma.getAreas(), areas))) {
						// DData check areas & roles
						locDData = new ArrayList<DData>();
						for (DData dd : ma.getDData()) {
							if (CollectionUtils.containsAny(dd.getRoles(), roles))
								locDData.add(dd);
						}
						// DPlot check areas & roles
						locDPlot = new ArrayList<DPlot>();
						for (DPlot dd : ma.getDPlot()) {
							if (CollectionUtils.containsAny(dd.getRoles(), roles))
								locDPlot.add(dd);
						}
						ma.setDData(locDData);
						ma.setDPlot(locDPlot);
					}
					locDMulti.add(ma);
				}
				localList.get(0).setdMultiAnalisys(locDMulti);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);
	}

	/**
	 * @deprecated
	 * @author valerio
	 * Return a DChildDatasetContainer not filtered.
	 * If no data is found return a void DParentDatasetContainer.
	 * @param areas
	 * @param roles
	 * @return DChildDatasetContainer
	 * 	DChildDatasetContainer
	 * 		DDataset
	 * 		DDataset
	 * 		...
	 */
	public static DChildDatasetContainer dlistdataset2pojo() {
		OrientDataset ods = new OrientDataset(orDb);
		List<DChildDatasetContainer> localList = orDb.query(new OSQLSynchQuery<DChildDatasetContainer>("select * from DListDataset"));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);

	}

	/**
	 * @author valerio
	 * Return a DChildDatasetContainer object with the data filtered according to the roles and areas included.
	 * If no data is found return a null DParentDatasetContainer.
	 * @param areas
	 * @param roles
	 * @return DChildDatasetContainer
	 * 	DChildDatasetContainer
	 * 		DDataset
	 * 		DDataset
	 * 		...
	 */
	public static DChildDatasetContainer dlistdataset2pojo(Collection<String> areas, Collection<String> roles) {
		Collection<DDataset> locDDataset = new ArrayList<DDataset>();

		OrientDataset ods = new OrientDataset(orDb);
		List<DChildDatasetContainer> localList = orDb.query(new OSQLSynchQuery<DChildDatasetContainer>("select * from DListDataset "));
		try {
			OrientUtilities.oLazyToEager(localList.get(0));
			for (DDataset dd : localList.get(0).getDataset()) {
				System.out.println(dd.getName()+" "+dd.getDimKb()+" "+dd.getNumCol()+dd.getNumRow());
				if (CollectionUtils.containsAny(dd.getAreas(), areas) && CollectionUtils.containsAny(dd.getRoles(), roles))
					locDDataset.add(dd);
			}

			localList.get(0).setDataset(locDDataset);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);

	}
	
	/**
	 * @author valerio
	 * Return a DParentDatasetContainer object with the data filtered according to the roles and areas included.
	 * If no data is found return a null DParentDatasetContainer.
	 * @param areas
	 * @param roles
	 * @return DParentDatasetContainer
	 * DParentDatasetContainer
	 * 		DChildDatasetContainer
	 * 			DDataset
	 * 			DDataset
	 * 			...
	 * 		DChildDatasetContainer
	 * 			DDataset
	 * 			DDataset
	 * 			...
	 * 		...
	 */
	public static DParentDatasetContainer dParentDatasetContainer2pojo(Collection<String> areas, Collection<String> roles) {

		OrientDataset ods = new OrientDataset(orDb);
		Collection<DChildDatasetContainer> locChildDatasetContainer = new ArrayList<DChildDatasetContainer>();
		Collection<DDataset> locDDataset = null;

		List<DParentDatasetContainer> localList = orDb.query(new OSQLSynchQuery<DParentDatasetContainer>("select * from DParentDatasetContainer "));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
			
			if (CollectionUtils.containsAny(localList.get(0).getAreas(), areas) && CollectionUtils.containsAny(localList.get(0).getRoles(), roles)) {

				// For each ChildDatasetContainer in ParentDatasetContainer
				for (DChildDatasetContainer childDatasetContainer : localList.get(0).getChildDatasetContainer()) {
					// check ares & roles
					//System.out.println(childDatasetContainer.getName());
					if (CollectionUtils.containsAny(childDatasetContainer.getAreas(), areas) && CollectionUtils.containsAny(childDatasetContainer.getRoles(), roles)) {
						// System.out.println(childDatasetContainer.getName());
						// For each DDataset in ChildDatasetContainer
						locDDataset = new ArrayList<DDataset>();
						for (DDataset dd : childDatasetContainer.getDataset()) {
							// Check areas & roles
							if (CollectionUtils.containsAny(dd.getAreas(), areas) && CollectionUtils.containsAny(dd.getRoles(), roles)) {
								// add Dataset on temporary Collection
								// (DDataset)
								locDDataset.add(dd);
							}
						}
						// add ListDataset on temporary Collection
						// (ChildDatasetContainer)
						childDatasetContainer.setDataset(locDDataset);
						// add ChildDatasetContainer on temporary Collection
						locChildDatasetContainer.add(childDatasetContainer);
					}
				}
			}
			// set ParentDatasetContainer on retrieved obj with Local Collection
			// of ChildDatasetContainer
			localList.get(0).setChildDatasetContainer(locChildDatasetContainer);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);
	}

	/**
	 * @deprecated
	 * @author valerio
	 * Return a DPreProcess object not filtered .
	 * If no data is found return a null DPreProcess. 
	 * @return DPreProcess
	 */
	public static DPreProcess dpreproc2pojo() {
		OrientPreProcess opp = new OrientPreProcess(orDb);
		List<DPreProcess> localList = orDb.query(new OSQLSynchQuery<DChildDatasetContainer>("select * from DPreProcess"));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);

	}

	/**
	 * @author valerio
	 * Return a DPreProcess object with the data filtered according to the roles and areas included.
	 * If no data is found return a null DPreProcess.
	 * @param areas
	 * @param roles
	 * @DPreProcess
	 */
	public static DPreProcess dpreproc2pojo(Collection<String> areas, Collection<String> roles) {
		Collection<DPreProcFunction> locPreProcFun = new ArrayList<DPreProcFunction>();
		OrientPreProcess opp = new OrientPreProcess(orDb);
		List<DPreProcess> localList = orDb.query(new OSQLSynchQuery<DChildDatasetContainer>("select * from DPreProcess "));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
			for (DPreProcFunction dpp : localList.get(0).getDPreProfunction()) {
				if (CollectionUtils.containsAny(dpp.getAreas(), areas) && CollectionUtils.containsAny(dpp.getRoles(), roles))
					locPreProcFun.add(dpp);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);

	}

	/**
	 * @author valerio
	 * Return a DConfig object not filtered .
	 * If no data is found return a null DConfig.
	 * @return DConfig
	 */
	public static DConfig dconfig2pojo() {
		OrientDConfig odc = new OrientDConfig(orDb);
		List<DConfig> localList = orDb.query(new OSQLSynchQuery<DConfig>("select * from DConfig"));

		try {
			OrientUtilities.oLazyToEager(localList.get(0));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return localList.get(0);

	}

	/**
	 * @author valerio
	 * Return a DConfig object with the data filtered according to the roles and areas included.
	 * If no data is found return a null DConfig.
	 * @param areas 
	 * @param roles
	 * @return DConfig 
	 */
	public static DConfig dconfig2pojo(Collection<String> areas, Collection<String> roles) {
		DConfig locDConfig = new DConfig();
		OrientDConfig odc = new OrientDConfig(orDb);
		List<DConfig> localList = orDb.query(new OSQLSynchQuery<DConfig>("select * from DConfig"));
		
		try {
			OrientUtilities.oLazyToEager(localList.get(0));
			if (CollectionUtils.containsAny(localList.get(0).getAreas(), areas) && CollectionUtils.containsAny(localList.get(0).getRoles(),roles))
			{
				localList.get(0).setListDMonoAnalisys(dmono2pojo(areas, roles));
				localList.get(0).setDMultiAnalisysContainer(dmulti2pojo(areas, roles));
				localList.get(0).setDPreProcess(dpreproc2pojo(areas, roles));
				localList.get(0).setParentDatasetContainer(dParentDatasetContainer2pojo(areas,roles));
				locDConfig = localList.get(0);
			}
				
		} catch (Exception e) {
			e.printStackTrace();
		}
		return locDConfig;
	}

}
